package com.job.client;

import com.alibaba.fastjson.JSON;
import com.job.common.DTO.JobInfoDTO;
import com.job.common.constant.OpenAPIConstant;
import com.job.common.exception.JobClientException;
import com.job.common.reference.TypeStore;
import com.job.common.returnT.ReturnT;
import com.job.common.utils.TokenUtils;
import com.job.common.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody;
import okhttp3.Headers;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * JobClient, the client for OpenAPI.
 *
 * @author songsong
 * @version 1.0
 * @date 2022/12/19 10:38
 **/
@Slf4j
public class JobClient {

    private String token;
    private final List<String> allAddress;

    private static final String URL_PATTERN = "http://%s%s%s";

    /**
     * Init JobClient with domain.
     *
     * @param domain like job-server.apple-inc.com (Intranet Domain)
     */
    public JobClient(String domain) {
        this(Arrays.asList(domain));
    }


    /**
     * Init JobClient with server address.
     *
     * @param addressList IP:Port address list, like 192.168.1.1:7700
     */
    public JobClient(List<String> addressList) {
        allAddress = addressList;
    }

    private static String getToken(String serverUrl) throws IOException {
        String url = getUrl(OpenAPIConstant.GET_TOKEN, serverUrl);
        FormBody.Builder builder = new FormBody.Builder();
        String tokenJson=HttpUtils.post(url, builder.build());
        ReturnT<String> t = JSON.parseObject(tokenJson, TypeStore.STRING_RESULT_TYPE);
        return t.getContent();
    }


    private static String getUrl(String path, String address) {
        return String.format(URL_PATTERN, address, OpenAPIConstant.WEB_PATH, path);
    }

    /* ************* Job 区 ************* */
    /**
     * Run a job once
     *
     * @param jobId          ID of the job to be run
     * @param executorParam Runtime parameters of the job (TaskContext#instanceParams)
     * @param addressList       run job address
     * @return instanceId
     */
    public ReturnT<Long> runJob(Long jobId, String executorParam, String addressList) {
        FormBody.Builder builder = new FormBody.Builder()
                .add("jobId", jobId.toString())
                .add("addressList", addressList)
                .add("executorParam", executorParam);
        String post = postHA(OpenAPIConstant.RUN_JOB, builder);
        return JSON.parseObject(post, TypeStore.LONG_RESULT_TYPE);
    }

    public ReturnT<Long> runJob(Long jobId) {
        return runJob(jobId, null, null);
    }


    public ReturnT<List<JobInfoDTO>> getAllRunJob(){
        String post = postHA(OpenAPIConstant.FETCH_ALL_JOB, new FormBody.Builder());
        return JSON.parseObject(post, TypeStore.LIST_JOB_RESULT_TYPE);
    }

    private String postHA(String path, FormBody.Builder builder) {
        for (String addr : allAddress) {
            String url = "";
            try {
                this.token = getToken(addr);
                Headers headers=new Headers.Builder().add(TokenUtils.RUN_ACCESS_TOKEN, token).build();
                url = getUrl(path, addr);
                String res = HttpUtils.headerPost(url, builder.build(),headers);
                if (StringUtils.isNotEmpty(res)) {
                    return res;
                }
            } catch (IOException e) {
                log.warn("[JobClient] request url:{} failed, reason is {}.", url, e.toString());
            }
        }

        log.error("[JobClient] do post for path: {} failed because of no server available in {}.", path, allAddress);
        throw new JobClientException("no server available when send post request");
    }
}
